# ROS 2 Humble Installation Guide This document describes how to build ROS 2 Humble from source on the Quectel Pi M1 development board (Debian 13 trixie / ARM64). The official ROS 2 Humble release targets Ubuntu 22.04; Debian 13 has no ready-made apt packages, so it must be built from source on the board. Every step in this document has been verified on the M1 (kernel 5.15.180-gki-consolidate, Python 3.13.5). ## Introduction ROS 2 (Robot Operating System 2) is a distributed communication framework for robotics development, and Humble is its long-term support (LTS) release. Building ROS 2 Humble from source on the M1 development board offers the following advantages: - Tailorable: Only build the packages you need, and skip commercial middleware such as Fast DDS or Connext (this document uses Cyclone DDS). - Board-level verification: Built directly on the M1's Debian 13 system, ensuring the artifacts match the hardware environment. - Reproducible: The workspace structure and build parameters can be templated, which facilitates CI and multi-device synchronization. **Disk space note:** The M1 root partition (/) is only 7.8 GB, while a full build requires more than 10 GB. This document deploys the workspace on the `/data` partition (about 40 GB, SD card mmcblk0p82); the full build was tested without any space pressure. ## Preparation ### System Requirements | **Item** | **Requirement** | | --- | --- | | Operating system | Debian GNU/Linux 13 (trixie) | | Architecture | ARM64 (aarch64) | | Disk | Recommended to deploy on the /data partition (root partition space is insufficient); source code about 1 GB, build artifacts about 3 GB | | Memory | ≥ 3 GB (M1 has 3.5 GB; build is slower but usable) | | Network | Able to access GitHub (clone source) and Debian package repos (install dependencies) | | Build time | About 3–5 hours (measured on M1, including troubleshooting) | ### Network Environment (Intranet / No External Network) If the board cannot connect to the external network directly, you can use **host proxy + adb reverse** to provide network access: ```bash # Host: start an HTTP proxy (e.g. a simple python proxy listening on port 3128) # Board: use adb reverse to forward the board's port 3128 to the host adb reverse tcp:3128 tcp:3128 # On the board, set the proxy environment variables export http_proxy=http://127.0.0.1:3128 https_proxy=http://127.0.0.1:3128 export HTTP_PROXY=http://127.0.0.1:3128 HTTPS_PROXY=http://127.0.0.1:3128 # Configure apt to use the proxy echo 'Acquire::http::Proxy "http://127.0.0.1:3128";' > /etc/apt/apt.conf.d/01proxy echo 'Acquire::https::Proxy "http://127.0.0.1:3128";' >> /etc/apt/apt.conf.d/01proxy ``` **Note:** The board's clock may be wrong (e.g. 1970), which causes HTTPS certificate verification to fail; synchronize the time first: `date -s "$(date '+%Y-%m-%d %H:%M:%S')"` (or configure NTP). ## Installation Steps ### Install Base Dependencies ```bash sudo apt-get update sudo apt-get install -y \\ python3-flake8-blind-except python3-flake8-class-newline python3-flake8-deprecated \\ python3-mypy python3-pip python3-pytest python3-pytest-cov python3-pytest-mock \\ python3-pytest-repeat python3-pytest-rerunfailures python3-pytest-runner \\ python3-pytest-timeout python3-rosdep2 python3-colcon-core \\ vcstool build-essential git \\ python3-numpy python3-numpy-dev \\ libacl1-dev uncrustify ``` ### Create the Workspace (Deploy to /data) ```bash # When the root partition has insufficient space, use the /data partition and create a symlink sudo mkdir -p /data/ros2_humble/src sudo ln -s /data/ros2_humble /root/ros2_humble cd /data/ros2_humble ``` ### Obtain the ROS 2 Humble Source Code ```bash cd /data/ros2_humble mkdir -p src wget https://raw.githubusercontent.com/ros2/ros2/humble/ros2.repos vcs import src < ros2.repos ``` ros2.repos contains about 100 repositories (105 measured); the source code is about 600 MB. If vcs gets stuck on a certain repository (such as the large Fast-DDS repo), you can fall back to a shallow-clone script that pulls them one by one. ### Install System Dependencies ```bash sudo rosdep init rosdep update cd /data/ros2_humble rosdep install --from-paths src --ignore-src --rosdistro humble -y -r \\ --skip-keys "fastcdr rti-connext-dds-6.0.1 urdfdom_headers python3-vcstool \\ ignition-math6 ignition-cmake2 ignition-common3 ignition-transport8" ``` **Skipped packages note:** fastcdr, rti-connext-dds (commercial/optional); urdfdom_headers, python3-vcstool (already installed); ignition-* (not available on Debian 13, Gazebo-related). **Common errors (can be ignored):** python3-sip-dev failure (pulled by the rqt GUI tool), python3-nose failure (deprecated in Python 3.12+); neither affects core functionality. ### Build the Source Code **Build strategy:** Use Cyclone DDS (skip Fast DDS/Connext to significantly reduce build time and space), and only build the minimum dependency chain up to demo_nodes: ```bash cd /data/ros2_humble export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp colcon build --symlink-install \\ --packages-up-to demo_nodes_cpp demo_nodes_py \\ --cmake-args -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF \\ --packages-skip \\ rmw_connextdds rmw_connextdds_common rmw_connextddsmicro rti_connext_dds_cmake_module \\ rviz_assimp_vendor tinyxml_vendor libcurl_vendor zstd_vendor sqlite3_vendor \\ yaml_cpp_vendor shared_queues_vendor ``` Measured build covered about 130 packages and took 40+ minutes (including the large packages such as fastrtps at 26 minutes and iceoryx_posh). After the build completes, you can additionally build the `ros2cli` command-line tools: ```bash source /data/ros2_humble/install/setup.bash colcon build --packages-select ros2cli ros2node ros2topic ros2msg ros2service ros2action ros2param \\ --cmake-args -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF ``` ### Build Issues and Solutions (Verified on M1) **Issue 1: rmw build fails with "unknown type name 'bool'"** Newer GCC is stricter, and `rmw/time.h` is missing `#include `. Fix: ```bash sed -i 's|#include |#include \\n#include |' \\ /data/ros2_humble/src/ros2/rmw/rmw/include/rmw/time.h ``` **Issue 2: vendor packages (zstd/sqlite3/yaml_cpp, etc.) time out during download and are aborted** These packages download third-party source code from the external network during the build; an unstable proxy causes failures. Solution: pre-download the archives via the proxy to the CMake cache path (`build/``/*-prefix/src/`); CMake skips the download when the file exists and its MD5 matches. For large files (e.g. assimp at 45 MB), download them on the host first and then adb push them to the board. **Issue 3: rmw_implementation fails with "Failed to find .../package.sh"** The build system looks for the package.sh environment hooks of the skipped packages. Work around it with placeholder scripts: ```bash for p in rti_connext_dds_cmake_module rmw_connextdds_common rmw_connextdds rmw_connextddsmicro; do mkdir -p /data/ros2_humble/install/$p/share/$p printf '#!/bin/sh\\n# placeholder for %s\\n' "$p" > /data/ros2_humble/install/$p/share/$p/package.sh chmod +x /data/ros2_humble/install/$p/share/$p/package.sh done ``` **Issue 4: rclpy build fails with 'Imported target "pybind11::headers" includes non-existent path "/include"'** This is a Debian packaging bug in pybind11's CMake prefix path. Fix pybind11Targets.cmake by hard-coding the include path: ```bash sed -i 's|INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"|INTERFACE_INCLUDE_DIRECTORIES "/usr/include"|' \\ /usr/lib/cmake/pybind11/pybind11Targets.cmake ``` **Issue 5: Message packages fail with ModuleNotFoundError** Missing lark (a dependency of rosidl_parser) and the numpy C header files: ```bash pip3 install lark netifaces apt-get install -y python3-numpy-dev # provides numpy/ndarrayobject.h ``` **Issue 6: rosidl_cli repeatedly fails with "File exists (package.dsv)"** A known conflict of symlink-install mode with the Python package resource files. Build it separately with copy mode first: ```bash rm -rf build/rosidl_cli install/rosidl_cli colcon build --packages-select rosidl_cli \\ --cmake-args -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF ``` **Issue 7: iceoryx_posh build times out and is aborted** This package takes 5–10 minutes to build and is judged to have timed out by colcon during parallel builds. Build it separately first: ```bash colcon build --packages-select iceoryx_posh \\ --cmake-args -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF ``` **Issue 8: rosidl_default_generators depends on rosidl_generator_rs (Rust)** demo_nodes does not require the Rust generator. Remove this dependency line from package.xml: ```bash sed -i '/rosidl_generator_rs/d' \\ /data/ros2_humble/src/ros2/rosidl_defaults/rosidl_default_generators/package.xml ``` ## Environment Variable Setup Once the build is complete, write the ROS 2 environment into `~/.bashrc` for auto loading: ```bash echo 'source /data/ros2_humble/install/setup.bash' >> ~/.bashrc echo 'export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp' >> ~/.bashrc source ~/.bashrc ``` ## Usage Test Open one terminal and run the C++ talker: ```bash ros2 run demo_nodes_cpp talker ``` Open another terminal and run the Python listener: ```bash ros2 run demo_nodes_py listener ``` ### Verification Measured output on the M1: ``` [INFO] [talker]: Publishing: 'Hello World: 3' [INFO] [listener]: I heard: [Hello World: 13] ``` You can also verify the topic with the ros2 command line: ```bash ros2 topic list # should show /chatter /parameter_events /rosout ros2 topic info /chatter # Type: std_msgs/msg/String, Publisher count: 1 ``` The C++ and Python APIs interoperate correctly, and the ROS 2 Humble environment is ready for subsequent application development. ## FAQ ### The ros2 command only shows daemon/extension_points This means the ros2cli extension commands (node, topic, etc.) are not installed. Follow section 3.5 to additionally build the ros2cli family of packages. ### ros2 topic reports "No module named 'netifaces'" ```bash pip3 install netifaces ``` ### talker fails to start with missing liblibstatistics_collector.so Not sourcing the environment causes LD_LIBRARY_PATH to be missing. Run `source /data/ros2_humble/install/setup.bash` before launching. ### Out of memory during the build (OOM) The M1 has 3.5 GB of memory, and a parallel build may OOM. Reduce the parallelism: `colcon build --parallel-workers 2 ...`, or pre-build the large packages separately as in section 3.5. ### Wrong board clock causes HTTPS failures ```bash sudo date -s "$(date '+%Y-%m-%d %H:%M:%S')" ``` ### Full ROS 2 packages (rviz2, etc.) This document is a minimal installation (the demo_nodes dependency chain). If you need GUI/simulation features, you can continue with `colcon build --packages-up-to rviz2 ...` to incrementally build them (mind the disk space).